
// /home/mathias/Sources/linux-2.6.31.5/arch/powerpc/include/asm/reg_booke.h

#define GET_SPR 0x1000
#define SET_SPR 0x2000

#define GET_MSR 0x4000
#define SET_MSR 0x8000

#define GET_DCR 0x10000
#define SET_DCR 0x20000

#define SPR_PVR 287

#define SPR_DEC 22
#define SPR_SRR0 26
#define SPR_SRR1 27

// PIR not implemented on 750
#define SPR_PIR 1023

// Non-440 specific registers
#define SPR_DBAT0U 536
#define SPR_DBAT0L 537
#define SPR_DBAT1U 538
#define SPR_DBAT1L 539
#define SPR_DBAT2U 540
#define SPR_DBAT2L 541
#define SPR_DBAT3U 542
#define SPR_DBAT3L 543
#define SPR_L2CR 1017
#define SPR_HID0 1008
#define SPR_HID1 1009
#define SPR_DABR 1013
#define SPR_ICTC 1019
#define SPR_THRM1 1020
#define SPR_THRM2 1021
#define SPR_THRM3 1022
#define SPR_DSISR 18
#define SPR_DAR 19
#define SPR_IABR 1010
#define SPR_DABR 1013 
#define SPR_EAR 282 

// 7447 specific registers
#define SPR_LDSTCR 1016
#define SPR_ICTRL 1011

// 750 specific registers
#define SPR_SDR1 0x19


// 440 specific registers
#define SPR_DECAR 0x036
#define SPR_CCR0 0x3b3
#define SPR_CCR1 0x378
#define SPR_DBCR0 0x134
#define SPR_DBCR1 0x135
#define SPR_DBCR2 0x136
#define SPR_DBSR 0x130
#define SPR_IAC1 0x138
#define SPR_IAC2 0x139
#define SPR_IAC3 0x13a
#define SPR_IAC4 0x13b
#define SPR_DAC1 0x13c
#define SPR_DAC2 0x13d
#define SPR_DVC1 0x13e
#define SPR_DVC2 0x13f
#define SPR_DBDR 0x3f3
#define SPR_CSRR0 26
#define SPR_CSRR1 27
#define SPR_MCSRR0 0x23a
#define SPR_MCSRR1 0x23b
#define SPR_DEAR 0x03d
#define SPR_ESR 0x03e
#define SPR_MCSR 0x23c
#define SPR_IVPR 0x03f
#define SPR_IVOR0 0x190
#define SPR_IVOR1 0x191
#define SPR_IVOR2 0x192
#define SPR_IVOR3 0x193
#define SPR_IVOR4 0x194
#define SPR_IVOR5 0x195
#define SPR_IVOR6 0x196
#define SPR_IVOR7 0x197
#define SPR_IVOR8 0x198
#define SPR_IVOR9 0x199
#define SPR_IVOR10 0x19a
#define SPR_IVOR11 0x19b
#define SPR_IVOR12 0x19c
#define SPR_IVOR13 0x19d
#define SPR_IVOR14 0x19e
#define SPR_IVOR15 0x19f
#define SPR_MMUCR 0x3b2
#define SPR_IVLIM 0x399

#define DCR_CPM0_ER 0x00b0
#define DCR_CPM0_FR 0x00b1
#define DCR_CPM0_SR 0x00b2

#ifndef __linux__

#define SPR_PVR 287

#define GET_PVR (GET_SPR | SPR_PVR)
//#define GET_MSR (GET_SPR | SPR_MSR)

#define mtspr(reg, val) \
	asm volatile ("mtspr %0, %1" :: "i" (reg), "r" (val))

#define mfspr(reg) \
	({ unsigned int ret; asm volatile ("mfspr %0, %1" : "=r" (ret) : "i" (reg)); \
		ret;})

#endif


/* Processor control */

// PVR

typedef union {
	unsigned int value;
	struct {
		unsigned int type : 16;
		unsigned int tech : 4;
		unsigned int major : 4;
		unsigned int minor : 8;
	};
} pvr_t;

// type :
// MPC7451/MPC7441 : 8000
// MPC7455/MPC7445 : 8001
// MPC7457/MPC7447 : 8002 (PowerBook G4)
// MPC7447A        : 8003 (MacMini G4)
// MPC7448         : 8004
// PPC440ep        : 4222 (18d3: rev B, 18d4: rev C)
// PPC460ex        : 1302
// MPC750          : 7002


// PIR

typedef unsigned int pir_t;

// MSR

typedef union {
	unsigned int value;
	struct {
		unsigned int reserved0 : 13;
		unsigned int we : 1; // Wait State Enable
		unsigned int ce : 1; // Critical Interrupt Enable
		unsigned int reserved : 1;
		unsigned int ee : 1; // External Interrupt Enable
		unsigned int pr : 1; // Problem State
		unsigned int fp : 1; // Floating Point Available
		unsigned int me : 1; // Machine Check Enable
		unsigned int fe0 : 1; // Floating Point Exception Mode 0
		unsigned int dwe : 1; // Debug Wait Enable
		unsigned int de : 1; // Debug Interrupt Enable
		unsigned int fe1 : 1; // Floating Point Exception Mode 1
		unsigned int reserved2 : 1;
		unsigned int is : 1; // Instruction Address Space
		unsigned int ds : 1; // Data Address Space
		unsigned int reserved3 : 4;
	};
} msr_booke_t;

typedef union {
	unsigned int value;
	struct {
		unsigned int reserved0 : 6;
		unsigned int vec : 1; // Vector Unit Available
		unsigned int reserved1 : 6;
		unsigned int pow : 1; // Power Management Enable
		unsigned int reserved2 : 1;
		unsigned int ile : 1; // Exception Little Endian Mode
		unsigned int ee : 1; // External Interrupt Enable
		unsigned int pr : 1; // Privilege Mode
		unsigned int fp : 1; // Floating Point Available
		unsigned int me : 1; // Machine Check Enable
		unsigned int fe0 : 1; // Floating Point Exception Mode 0
		unsigned int se : 1; // Single Trace Enable
		unsigned int be : 1; // Branch Trace Enable
		unsigned int fe1 : 1; // Floating Point Exception Mode 1
		unsigned int reserved3 : 1;
		unsigned int ip : 1; // Exception Prefix
		unsigned int ir : 1; // Instruction Address Translation
		unsigned int dr : 1; // Data Address Translation
		unsigned int reserved4 : 1;
		unsigned int pmm : 1; // Performance Monitor Marked Mode
		unsigned int ri : 1; // System Reset Or Machine Check Exception Recoverable
		unsigned int le : 1; // Little Endian Mode
	};
} msr_t;

static inline unsigned int get_msr(void)
{
	unsigned int msr;
	asm volatile ("mfmsr %0" : "=r" (msr));
	return msr;
}

#if 1

// BAT

static inline unsigned int get_dbat0(void)
{
	unsigned int bat;
	asm volatile ("mfspr %0, 536" : "=r" (bat));
	return bat;
}

static inline unsigned int get_dbat1(void)
{
	unsigned int bat;
	asm volatile ("mfspr %0, 538" : "=r" (bat));
	return bat;
}

static inline unsigned int get_dbat2(void)
{
	unsigned int bat;
	asm volatile ("mfspr %0, 540" : "=r" (bat));
	return bat;
}

static inline unsigned int get_dbat3(void)
{
	unsigned int bat;
	asm volatile ("mfspr %0, 542" : "=r" (bat));
	return bat;
}

#if 0
static const int dbat_array[] = {536, 538, 540, 542};

static unsigned int get_dbat(int index)
{
	unsigned int dbat;
	asm volatile ("mfspr %0, %1" : "=r" (dbat) : "n" (index));
	return dbat;
}
#endif

// MMUCR

typedef union {
	unsigned int value;
	struct {
		unsigned int reserved1 : 7;
		unsigned int swoa: 1; // Store Without Allocate
		unsigned int reserved2 : 1;
		unsigned int u1te : 1; // U1 Transient Enable
		unsigned int u2swoae : 1; // U2 Store Without Allocate Enable
		unsigned int reserved3 : 1;
		unsigned int dulxe : 1; // Data Cache Unlock Exception Enable
		unsigned int iulxe : 1; // Instruction Cache Unlock Exception Enable
		unsigned int reserved4 : 1;
		unsigned int sts : 1; // Search Translation Space
		unsigned int reserved5 : 8;
		unsigned int stid : 8; // Search Translation ID
	};
} mmucr_t;

// SDR1 contains the address of the page table used in virtual to physical address translation

typedef union {
	unsigned int value;
	struct {
		unsigned int HTABORG : 16; // Physical base address of page table
		unsigned int HTABEXT : 3; // Extension bits for physical base addess of page table
		unsigned int HTMEXT : 4; // Hash table mask extension bits
		unsigned int HTABMASK : 9; // Mask for page table address
	};
} sdr1_t;

// CCR0
// Controls the speculative prefetch mechanism and the behavior of the icbt
// instruction. The CCR0 register also controls various other functions within
// the PPC440x6 core that are unrelated to the instruction cache.

typedef union {
	unsigned int value;
	struct {
		unsigned int reserved0 : 1;
		unsigned int pre : 1; // Parity Recoverability Enable
		unsigned int reserved1 : 2;
		unsigned int cpre : 1; // Cache Read Parity Enable
		unsigned int reserved2 : 5;
		unsigned int dstg : 1; // Disable Store Gathering
		unsigned int dapuib : 1; // Disable APU Instruction Broadcast
		unsigned int reserved3 : 4;
		unsigned int dtb : 1; // Disable Trace Broadcast
		unsigned int gicbt : 1; // Guaranteed Instruction Cache Block Touch
		unsigned int gdcbt : 1; // Guaranteed Data Cache Block Touch
		unsigned int reserved4 : 4;
		unsigned int flsta : 1; // Force Load/Store Alignment
		unsigned int reserved5 : 8; 
	};
} ccr0_t;

// CCR1
// The CCR1 register controls parity error insertion for software testing,
// one option for line flush behavior in the D-cache, and a control bit
// that selects the timer input clock.

typedef union {
	unsigned int value;
	struct {
		unsigned int icdpei : 8; // Instruction Cache Data Parity Error Insert
		unsigned int ictpei : 2; // Instruction Cache Tag Parity Error Insert
		unsigned int dctpei : 2; // Data Cache Tag Parity Error Insert
		unsigned int dcdpei : 1; // Data Cache Data Parity Error Insert
		unsigned int dcupei : 1; // Data Cache U-bit Parity Error Insert
		unsigned int dcmpei : 1; // Data Cache Modified-bit Parity Error Insert
		unsigned int fcom : 1; // Force Cache Operation Miss
		unsigned int mmupei : 4; // Memory Management Unit Parity Error Insert
		unsigned int fff : 1; // Force Full-line Flush
		unsigned int reserved0 : 3;
		unsigned int tcs : 1; // Timer Clock Select
		unsigned int reserved1 : 7;
	};
} ccr1_t;

/* Cache control */

// IVLIM

typedef union {
	unsigned int value;
	struct {
		unsigned int reserved1 : 2;
		unsigned int tfloor : 8; // Transient floor
		unsigned int reserved2 : 3;
		unsigned int tceiling : 8; // Transient ceiling
		unsigned int reserved3 : 3;
		unsigned int nfloor : 8; // Normal floor
	};
} ivlim_t;

// L2CR

typedef union {
	unsigned int value;
	struct {
		unsigned int l2e : 1; // L2 Enable
		unsigned int l2pe : 1; // L2 Data Parity Generation and Checking Enable
		unsigned int reserved0 : 8;
		unsigned int l2i : 1; // L2 Global Invalidate
		unsigned int l2io : 1;
		unsigned int reserved1 : 3;
		unsigned int l2do : 1; // L2 Data Only
		unsigned int reserved2 : 3;
		unsigned int l2rep : 1;
		unsigned int l2hwf : 1;
		unsigned int reserved3 : 11;
	};
} l2cr_t;

typedef union {
	unsigned int value;
	struct {
		unsigned int l2e : 1; // L2 Enable
		unsigned int l2pe : 1; // L2 Data Parity Generation and Checking Enable
		unsigned int l2siz : 2; // L2 Size
		unsigned int l2clk : 3; // L2 Clock Ratio
		unsigned int l2ram : 2; // L2 RAM type
		unsigned int l2do : 1; // L2 Data Only
		unsigned int l2i: 1; // L2 Global Invalidate
		unsigned int l2ctl : 1; // L2 RAM Control (ZZ Enable)
		unsigned int l2wt : 1; // L2 Write-Through
		unsigned int l2ts : 1; // L2 Test Support
		unsigned int l2oh : 2; // L2 Output Hold
		unsigned int l2sl : 1; // L2 DLL Slow
		unsigned int l2dl : 1; // L2 Differencial Clock
		unsigned int l2byp : 1; // L2 DLL Bypass
		unsigned int reserved : 3;
		unsigned int l2cs : 2; // L2 Clock Stop
		unsigned int l2dro : 1; // L2 DLL Rollover Checkstop Enable
		unsigned int l2ctr : 1; // L2 DLL Counter Value (RO)
		unsigned int l2ip : 1; // L2 Global Invalidate In Progress (RO)
	};
} l2cr_7002_t;

// ICTRL

// LDSTCR

// HID0

typedef union {
	unsigned int value;
	struct {
		unsigned int reserved0 : 5;
		unsigned int tben : 1; // Time Base Enable
		unsigned int reserved1 : 1;
		unsigned int sten : 1; // Software Table search Enable
		unsigned int high_bat_en : 1; // Additional BATs enabled (reserved on MPC7451/MPC7441)
		unsigned int nap : 1; // Nap mode enable
		unsigned int sleep : 1; // Sleep mode enable
		unsigned int dpm : 1; // Dynamic Power Management enable
		unsigned int reserved3 : 1;
		unsigned int bhtclr : 1; // Clear Branch History Table
		unsigned int xaen : 1; // Extended Addressing Enable
		unsigned int nhr : 1; // Not Hard Reset
		unsigned int ice : 1; // Instruction Cache Enable
		unsigned int dce : 1; // Data Cache Enable
		unsigned int ilock : 1; // Instruction Cache Lock
		unsigned int dlock : 1; // Data Cache Lock
		unsigned int icfi : 1; // Instruction Cache Flash Invalidate
		unsigned int dcfi : 1; // Data Cache Flash Invalidate
		unsigned int spd : 1; // Speculative Data Cache and Instruction Cache Access Disable
		unsigned int xbsen : 1; // Extended BAT block size enable (reserved on MPC7451/MPC7441)
		unsigned int sge : 1; // Store Gathering Enable
		unsigned int reserved5 : 1;
		unsigned int btic : 1; // Branch Target Instruction Cache Enable
		unsigned int lrstk : 1; // Link Register Stack Enable
		unsigned int fold : 1; // Branch Folding Enable
		unsigned int bht : 1; // Branch History Table Enable
		unsigned int nopdst : 1; // No-op dst, dstt, dstst and dststt
		unsigned int nopti : 1; // No-op the data cache touch instructions (dcbt, dcbst)
	};
} hid0_t;

typedef union {
	unsigned int value;
	struct {
		unsigned int emcp : 1; // Enable MCP signal
		unsigned int dbp : 1; // Enable 60x bus address and data parity generation
		unsigned int eba : 1; // Enable 60x bus address parity checking
		unsigned int ebc : 1; // Enable 60x bus data parity checking
		unsigned int bclk : 1;
		unsigned int reserved1 : 1;
		unsigned int eclk : 1;
		unsigned int par : 1; // Disable precharge of ARTRY signal
		unsigned int doze : 1; // Doze Mode Enable
		unsigned int nap : 1; // Nap Mode Enable
		unsigned int sleep : 1; // Sleep Mode Enable
		unsigned int dpm : 1; // Dynamic Power Management enable
		unsigned int reserved2 : 3;
		unsigned int nhr : 1; // Not Hard Reset
		unsigned int ice : 1; // Instruction Cache Enable
		unsigned int dce : 1; // Data Cache Enable
		unsigned int ilock : 1; // Instruction Cache Lock
		unsigned int dlock : 1; // Data Cache Lock
		unsigned int icfi : 1; // Instruction Cache Flash Invalidate
		unsigned int dcfi : 1; // Data Cache Flash Invalidate
		unsigned int spd : 1; // Speculative Data Cache and Instruction Cache Access Disable
		unsigned int ifem : 1; // Enable M bit on bus for instruction fetches
		unsigned int sge : 1; // Store Gathering Enable
		unsigned int dcfa : 1; // Data Cache Flush Assist
		unsigned int btic : 1; // Branch Target Instruction Cache Enable
		unsigned int reserved3 : 1;
		unsigned int abe : 1; // Address Broadcast Enable
		unsigned int bht : 1; // Branch History Table Enable
		unsigned int rserved4 : 1;
		unsigned int nopti : 1; // No-op the data cache touch instructions (dcbt, dcbst)
	};
} hid0_7002_t;

/* MMU configuration */

// MMUCR on 440


/* Debug support */

// DABR


// DBCR0 is an SPR that is used to enable debug modes and events, reset the processor,
// and control timer operation when debugging.

typedef union {
	unsigned int value;
	struct {
		unsigned int edm : 1; // External Debug Mode
		unsigned int idm : 1; // Internal Debug Mode
		unsigned int rst : 2; // Reset
		unsigned int icmp : 1; // Instruction Completion Debug Event
		unsigned int brt : 1; // Branch Taken Debug Event
		unsigned int irpt : 1; // Interrupt Debug Event
		unsigned int trap : 1; // Trap Debug Event
		unsigned int iac1 : 1; // Instruction Address Compare (IAC) 1 Debug Event
		unsigned int iac2 : 1; // Instruction Address Compare (IAC) 2 Debug Event
		unsigned int iac3 : 1; // Instruction Address Compare (IAC) 3 Debug Event
		unsigned int iac4 : 1; // Instruction Address Compare (IAC) 4 Debug Event
		unsigned int dac1r : 1; // Data Address Compare (DAC) 1 Read Debug Event
		unsigned int dac1w : 1; // Data Address Compare (DAC) 1 Write Debug Event
		unsigned int dac2r : 1; // Data Address Compare (DAC) 2 Read Debug Event
		unsigned int dac2w : 1; // Data Address Compare (DAC) 2 Write Debug Event
		unsigned int ret : 1; // Return Debug Event
		unsigned int reserved1 : 14;
		unsigned int ft : 1; // Freeze Timers On Debug Event
	};
} dbcr0_t;

// DBCR1 is an SPR that is used to configure IAC debug events.

typedef union {
	unsigned int value;
	struct {
		unsigned int iac1us : 2; // IAC 1 User/Supervisor
		unsigned int iac1er : 2; // IAC 1 Effective/Real
		unsigned int iac2us : 2; // IAC 2 User/Supervisor 
		unsigned int iac2er : 2; // IAC 2 Effective/Real
		unsigned int iac12m : 2; // IAC 1/2 Mode
		unsigned int reserved1 : 5;
		unsigned int iac12at : 2; // IAC 1/2 Auto-Toggle Enable
		unsigned int iac3us : 2; // IAC 3 User/Supervisor
		unsigned int iac3er : 2; // IAC 3 Effective/Real
		unsigned int iac4us : 2; // IAC 4 User/Supervisor 
		unsigned int iac4er : 2; // IAC 4 Effective/Real
		unsigned int iac34m : 2; // IAC 3/4 Mode
		unsigned int reserved2 : 5;
		unsigned int iac34at : 2; // IAC 3/4 Auto-Toggle Enable
	};
} dbcr1_t;

typedef union {
	unsigned int value;
	struct {
		unsigned int dac1us : 2; // DAC 1 User/Supervisor
		unsigned int dac1er : 2; // DAC 1 Effective/Real
		unsigned int dac2us : 2; // DAC 2 User/Supervisor 
		unsigned int dac2er : 2; // DAC 2 Effective/Real
		unsigned int dac12m : 2; // DAC 1/2 Mode
		unsigned int dac12a : 1; // DAC 1/2 Asynchronous
		unsigned int reserved1 : 1;
		unsigned int dvc1m : 2; // DVC 1 Mode
		unsigned int dvc2m : 2; // DVC 2 Mode
		unsigned int reserved2 : 4;
		unsigned int dvc1be : 4; // DVC 1 Byte Enables 0:3
		unsigned int reserved3 : 4;
		unsigned int dvc2be : 4; // DVC 2 Byte Enables 0:3
	};
} dbcr2_t;

typedef union {
	unsigned int value;
	struct {
		unsigned int ide : 1; // Imprecise Debug Event
		unsigned int ude : 1; // Unconditional Debug Event
		unsigned int mrr : 2; // Most Recent Reset
		unsigned int icmp : 1; // Instruction Completion Debug Event
		unsigned int brt : 1; // Branch Taken Debug Event
		unsigned int irpt : 1; // Interrupt Debug Event
		unsigned int trap : 1; // Trap Debug Event
		unsigned int iac1 : 1; // IAC 1 Debug Event
		unsigned int iac2 : 1; // IAC 2 Debug Event
		unsigned int iac3 : 1; // IAC 3 Debug Event
		unsigned int iac4 : 1; // IAC 4 Debug Event
		unsigned int dac1r : 1; // DAC 1 Read Debug Event
		unsigned int dac1w : 1; // DAC 1 Write Debug Event
		unsigned int dac2r : 1; // DAC 2 Read Debug Event
		unsigned int dac2w : 1; // DAC 2 Write Debug Event
		unsigned int ret : 1; // Return  Debug Event
		unsigned int reserved : 13;
		unsigned int iac12ats : 1; // IAC 1/2 Auto-Toggle Status
		unsigned int iac34ats : 1; // IAC 3/4 Auto-Toggle Status
	};
} dbsr_t;

// ICTC (Instruction Cache Throttling Control register)

typedef union {
	unsigned int value;
	struct {
		unsigned int reserved : 23;
		unsigned int fi : 8; // Forwarding interval (in processor clocks)
		unsigned int e : 1; // Enable throttling
	};
} ictc_t;

static inline unsigned int get_ictc(void)
{
	unsigned int ictc;
	asm volatile ("mfspr %0, 1019" : "=r" (ictc));
	return ictc;
}

// RSTCFG (0x39b) on 440
// The read-only RSTCFG register reports the values of certain fields of TLB as supplied at reset.

// THRMx

typedef union {
	unsigned int value;
	struct {
		unsigned int tin : 1; // Thermal Management Interrupt Bit (RO)
		unsigned int tiv : 1; // Thermal Management Interrupt Valid (RO)
		unsigned int threshold : 7; // Threshold value
		unsigned int reserved : 20;
		unsigned int tid : 1; // Thermal Management Interrupt Direction Bit
		unsigned int tie : 1; // Thermal Management Interrupt Enable
		unsigned int v : 1; // Valid Bit (SPR contains a valid thresold)
	};
} thrm1_t;

typedef union {
	unsigned int value;
	struct {
		unsigned int reserved : 18;
		unsigned int sitv : 13; // Sample Interval Timer Value
		unsigned int e : 1; // Enable Thermal Sensor Compare Operation
	};
} thrm3_t;

#endif

